-
Notifications
You must be signed in to change notification settings - Fork 1
feat(buckets/policy): add bucket policy UI, handlers, MinIO client methods, and tests #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Thanks 👍 Can you provide a quick screenshot of the new functionality please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds bucket policy support across the UI and backend so users can view and set bucket access policies (private / public-read / public-read-write / custom), and exposes policy status in bucket listings and the object browser.
Changes:
- Add bucket policy view/edit UI (settings card + reusable partial) and policy badges in bucket list/browser.
- Add MinIO client interface methods + new Echo handlers/routes to get/set bucket policies.
- Add unit tests for policy JSON canonicalization/type detection and update journey test mocks for new policy lookups.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
views/partials/bucket_policy.html |
New reusable HTMX/Alpine bucket policy editor fragment. |
views/pages/buckets.html |
Shows a policy-type badge next to each bucket in the list. |
views/pages/bucket_settings.html |
Adds a bucket policy settings section (currently duplicated vs partial). |
views/pages/browser.html |
Adds policy badge/modal and “Direct Link” dialog + copy action. |
views/layouts/base.html |
Removes global HTMX boosted navigation attributes from <body>. |
internal/services/minio_factory.go |
Extends MinioClient with bucket policy methods; exports ShouldUseSSL. |
internal/renderer/renderer.go |
Registers bucket_policy as a self-executing partial template. |
internal/handlers/policy_test.go |
Adds tests for canonicalJSON and detectPolicyType. |
internal/handlers/buckets_handler.go |
Fetches policy + type in list/browser/settings; adds get/set policy handlers. |
cmd/server/mocks_test.go |
Adds mocked GetBucketPolicy/SetBucketPolicy. |
cmd/server/main.go |
Registers new bucket policy routes. |
cmd/server/bucket_journey_test.go |
Updates mocks to account for policy lookups in journeys. |
views/pages/bucket_settings.html
Outdated
| <div class="space-y-4" x-data="{ | ||
| policyType: '{{ .PolicyType }}', | ||
| customPolicy: '', | ||
| showEditor: {{ if eq .PolicyType "custom" }}true{{ else }}false{{ end }}, | ||
| init() { | ||
| const el = this.$refs.policyData; | ||
| if (el && el.value) this.customPolicy = el.value; | ||
| } | ||
| }"> | ||
| <textarea x-ref="policyData" class="hidden">{{ .FormattedPolicy }}</textarea> | ||
|
|
Copilot
AI
Feb 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bucket policy UI is duplicated inline here, while there is also a new reusable views/partials/bucket_policy.html fragment and a GET /buckets/:bucketName/policy handler. Keeping two copies increases the chance of UI drift and makes HTMX updates harder.
Consider loading the policy section the same way as the other settings cards (e.g., hx-get on load to render the bucket_policy partial) and removing the duplicated markup from this page.
views/partials/bucket_policy.html
Outdated
| <form hx-post="/buckets/{{ .BucketName }}/policy" class="space-y-4 pt-4 border-t border-zinc-700"> | ||
| <div> | ||
| <label class="block text-xs text-zinc-500 mb-2">Access Policy</label> | ||
| <div class="grid grid-cols-2 gap-2"> | ||
| <label class="flex items-center gap-2 p-3 bg-zinc-800/50 rounded-lg cursor-pointer border border-transparent hover:border-zinc-600 transition-colors" |
Copilot
AI
Feb 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This policy form has no hx-target/hx-swap. Since SetBucketPolicy returns the full bucket_policy fragment on errors, HTMX will replace only the <form> by default, leaving the rest of the component stale and potentially nesting fragments.
Add a stable wrapper (id/class) and set the form to target/swap that wrapper so the whole component updates together on both success and error paths.
| const url = '{{ .EndpointURL }}/{{ .BucketName }}/' + key; | ||
| this.directLinkURL = url; | ||
| this.directLinkDialogOpen = true; | ||
| this.$nextTick(() => lucide.createIcons()); | ||
| }, | ||
|
|
||
| copyDirectLinkToClipboard() { | ||
| navigator.clipboard.writeText(this.directLinkURL); |
Copilot
AI
Feb 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copyDirectLink builds a URL by string concatenation without URL-encoding the object key. Keys containing spaces, #, ?, or non-ASCII characters will produce invalid links.
Use proper URL construction/encoding (e.g., encode the key path segment) and consider handling the navigator.clipboard.writeText(...) promise to report failures (clipboard APIs often require HTTPS/permissions).
| const url = '{{ .EndpointURL }}/{{ .BucketName }}/' + key; | |
| this.directLinkURL = url; | |
| this.directLinkDialogOpen = true; | |
| this.$nextTick(() => lucide.createIcons()); | |
| }, | |
| copyDirectLinkToClipboard() { | |
| navigator.clipboard.writeText(this.directLinkURL); | |
| const encodedKey = encodeURIComponent(key); | |
| const url = '{{ .EndpointURL }}/{{ .BucketName }}/' + encodedKey; | |
| this.directLinkURL = url; | |
| this.directLinkDialogOpen = true; | |
| this.$nextTick(() => lucide.createIcons()); | |
| }, | |
| copyDirectLinkToClipboard() { | |
| if (!navigator.clipboard || !navigator.clipboard.writeText) { | |
| console.error('Clipboard API is not available in this browser/context.'); | |
| alert('Clipboard is not available. Please copy the link manually.'); | |
| return; | |
| } | |
| navigator.clipboard.writeText(this.directLinkURL) | |
| .then(() => { | |
| // Optionally, you could show a success notification here. | |
| }) | |
| .catch((err) => { | |
| console.error('Failed to copy direct link to clipboard:', err); | |
| alert('Failed to copy link to clipboard. Please copy it manually.'); | |
| }); |
|
|
||
| <body class="bg-background text-zinc-100 h-screen w-screen flex overflow-hidden" x-data="{ collapsed: false }" | ||
| hx-boost="true" hx-target="#main-content" hx-select="#main-content" hx-swap="outerHTML"> | ||
| <body class="bg-background text-zinc-100 h-screen w-screen flex overflow-hidden" x-data="{ collapsed: false }"> |
Copilot
AI
Feb 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing hx-boost/hx-target/hx-select/hx-swap from the <body> changes navigation behavior application-wide (links will no longer be boosted into #main-content). This appears unrelated to the bucket policy feature set and could regress UX/performance.
If this was intentional, consider keeping the boosted navigation (or replacing it with a narrower scope) and remove the now-redundant hx-boost="false" usage on the logout link; otherwise, revert this change to keep the PR scoped.
|
Thanks for the PR. Ca ln you address the comments please. The main one I'm concerned about is squashing error codes. |
…icy state and x-cloak in template
…h error details when GetBucketPolicy fails
…TMX partial swap of policy section
|
Amazing, thank you very much for this. |
|
Ping me when the tests are working! :D |






No description provided.